iT邦幫忙

2023 iThome 鐵人賽

DAY 3
1
AI & Data

從零到英雄:用GCP建立AI交易體系系列 第 3

建立交易模型的下一步:特徵選擇和準備

  • 分享至 

  • xImage
  •  

今天的開頭我們先看看下圖昨天的label結果:


基本上沒有極大的偏向,11:17:13的比例也算是很不錯。

接續下去的話我們就來進行特徵建立吧!

技術指標作為特徵

技術指標作為特徵是相對簡單的,並且在實際交易上感覺有用,但是仔細一想就會發現技術指標本身會對於交易資訊有省略的意涵。(沒錯這是一個坑),但是現在我們先用技術指標吧~

技術指標分成幾類,我挑三種來講,根據過去我做的研究也可以靠這三種有不錯的預測績效:

  • 趨勢指標:在趨勢盤表現較好的指標,例如D+、D-等等
  • 震盪指標:震盪盤表現較好的指標,例如KD、布林軌道等等
  • 波動率指標:只用於表現是否會有大行情、波動率是否大的指標,例如標準差

根據我過去研究(如果想看我們可以另外開一集來講),標準差會很大程度上幫助指標運算,震盪指標就挑KD。先以這兩個指標先做,之後想要增加其他的內容我們可以慢慢處理。

先來寫點Code產生技術指標吧!

import talib as ta
import pandas as pd

def calculate_stoch_by_talib(dataframe):
    # 使用talib計算STOCH指標
    slowk, slowd = ta.STOCH(dataframe['high'], dataframe['low'], dataframe['close'],
                            fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)
    
    # 將結果四捨五入到小數兩位
    slowk = round(slowk, 2)
    slowd = round(slowd, 2)
    
    return slowk, slowd

# 讀取CSV文件
df = pd.read_csv('label_data.csv')

# 根據股票代號分割資料並計算STOCH指標,然後加入到df中
for stock in df['股票代號'].unique():
    stock_data = df[df['股票代號'] == stock]
    slowk, slowd = calculate_stoch_by_talib(stock_data)
    
    # 將計算結果加入到原始資料中,並在欄位名稱上標記參數
    df.loc[stock_data.index, 'slowk_5_3_3'] = slowk
    df.loc[stock_data.index, 'slowd_5_3_3'] = slowd

# 儲存結果到新的CSV文件
df.to_csv('label_data_with_stoch.csv', index=False, encoding='utf_8_sig')

大致上做完就可以改一下準備大量生產不同參數的資料

import talib as ta
import pandas as pd
from itertools import product

def calculate_stoch_by_talib(dataframe, fastk_period, slowk_period, slowd_period):
    # 使用talib計算STOCH指標
    slowk, slowd = ta.STOCH(dataframe['high'], dataframe['low'], dataframe['close'],
                            fastk_period=fastk_period, 
                            slowk_period=slowk_period, 
                            slowk_matype=0, 
                            slowd_period=slowd_period, 
                            slowd_matype=0)
    
    # 將結果四捨五入到小數兩位
    slowk = round(slowk, 2)
    slowd = round(slowd, 2)
    
    return slowk, slowd

# 讀取CSV文件
df = pd.read_csv('label_data.csv')

# 定義參數範圍
fastk_range = range(5, 11)  
slowk_period_range = range(3, 6)
slowd_range = range(3, 6)

combinations = product(fastk_range, slowk_period_range, slowd_range)

# 根據股票代號分割資料並計算STOCH指標,然後加入到df中
for fastk, slowk_period, slowd in combinations:
    for stock in df['股票代號'].unique():
        stock_data = df[df['股票代號'] == stock]
        slowk_values, slowd_values = calculate_stoch_by_talib(stock_data, fastk, slowk_period, slowd)
        
        # 根據參數組合調整欄位名稱,並將計算結果加入到原始資料中
        df.loc[stock_data.index, f'slowk_{fastk}_{slowk_period}_{slowd}'] = slowk_values
        df.loc[stock_data.index, f'slowd_{fastk}_{slowk_period}_{slowd}'] = slowd_values

# 儲存結果到新的CSV文件
df.to_csv('label_data_with_stoch.csv', index=False, encoding='utf_8_sig')

特徵篩選

機器學習中雖然理論上越多特徵越容易擬合現實函數,但是也會因為數據過多導致 1. 運算速度變慢 2. 收斂不容易。因此我們會希望採用特徵篩選的方式去挑選我們的特徵。特徵的挑選方式有很多種:

  1. 過濾法

    • 過程:這種方法首先評估每個特徵與目標變量之間的相關性,通常使用統計指標(例如相關係數、卡方檢驗、互信息等)來評分特徵。然後,你可以設定閾值或者選擇預定數量的特徵,來確定最終的特徵集合。
    • 優點:速度快,能夠一次處理所有特徵,適用於大規模數據。不需要訓練模型,因此計算成本較低。
    • 缺點:特徵選擇過程和模型評估是分開進行的,所以選出的特徵集合未必是最適合模型的。它可能忽略了特徵之間的交互作用。
  2. 包裝法

    • 過程:這種方法將特徵選擇與模型評估結合在一起。它使用一個目標函數(例如交叉驗證的性能分數)來評估每個特徵子集的表現。通常,它會嘗試多個不同的特徵子集,並找出最佳的組合。
    • 優點:能夠考慮特徵之間的交互作用,可以找到最適合模型的特徵組合。它直接使用模型性能來評估特徵的價值。
    • 缺點:運行時間通常較長,因為它需要訓練多個模型來評估不同的特徵子集,這可能導致計算成本增加。此外,如果不小心,可能會導致模型過度擬合,因為它試圖擬合許多不同的特徵組合。

我們可以先採用包裝法(反正我們現在時間多)。會選擇一個有特徵重要性的模型,這時候我們可以選擇基於樹的模型,進行初步的模型訓練之後選擇特徵重要性較高的特徵。這部分有一個坑,如果選擇邏輯回歸等等模型會有共線性的問題。

當有兩個或更多自變數之間存在高度相關(即彼此相關),則稱為「共線性」。共線性可能導致迴歸模型中存在重複的自變數,進而引起模型權重不穩定的問題。

以下是使用決策樹進行的特徵篩選,我們會選取表現最佳的6個參數:

import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.feature_selection import RFECV
from sklearn.model_selection import StratifiedKFold

# 重新載入數據
data = pd.read_csv('label_data_with_stoch.csv')

# 移除不可使用的欄位
data_cleaned = data.drop(columns=['前10日最高價標準差', '前10日最低價標準差', '最高價+2倍標準差', '最低價-2倍標準差'])

# 移除空值
data_cleaned = data_cleaned.dropna(subset=['label'])

# 分割特徵和目標
X = data_cleaned.drop(columns=['股票代號', '股票名稱', '日期', 'label'])
y = data_cleaned['label']

# 至少要保留幾個特徵
min_features_to_select = 6

# 定義模型
estimator = DecisionTreeClassifier()

# 定義 RFE 與交叉驗證策略
rfecv = RFECV(estimator=estimator, step=1, cv=StratifiedKFold(5),
              scoring='accuracy', min_features_to_select=min_features_to_select)
rfecv.fit(X.fillna(0), y)

# 顯示選擇的特徵
selected_features = X.columns[rfecv.support_]
selected_features_list = list(selected_features)
print(selected_features_list)

RFECV(帶有交叉驗證的遞歸特徵消除),是一種特徵篩選方式,其中包含RFE、CV兩部分:

  1. 遞歸特徵消除(RFE)

    • RFECV的核心思想是反覆執行特徵消除過程。它首先使用所有特徵訓練模型,然後評估每個特徵的重要性。接著,它刪除最不重要的特徵,重新訓練模型,再次評估特徵的重要性。這個過程持續反覆,每次都刪除一個或多個最不重要的特徵,直到達到停止條件(例如,選擇固定數量的特徵或達到特定性能閾值)為止。
  2. 交叉驗證(CV)

    • RFECV使用交叉驗證來評估特徵的性能。交叉驗證是將數據集分成多個子集(折),然後多次訓練模型,每次使用不同的子集作為測試集,其餘子集用於訓練。

RFECV參數的詳細解釋:

  1. estimator:機器學習模型。
  2. step:每次特徵選擇過程中要刪除的特徵數目。
  3. cv:用於評估特徵性能的交叉驗證策略。
  4. scoring:評估模型性能的指標。
  5. min_features_to_select:設置要選擇的最小特徵數目。

特徵篩選完之後我們就可以留下我們的特徵冠軍們。明天我們將一起進行模型建立的步驟,而特徵的結果也會一併在明天公布(畢竟運算KD跟標準差兩種都很消耗資源)


上一篇
Day2 標記在股市上的各種眉角
下一篇
使用隨機森林建立股票預測模型
系列文
從零到英雄:用GCP建立AI交易體系34
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言